/**
 * @file   transition_map.hpp
 * @author Kimmo Luoma <kimmo@PHOTON3>
 * @date   Fri Sep  7 11:41:29 2012
 * 
 * @brief  Transition map class 
 * 
 */

#ifndef TRANSITION_MAP_HPP
#define TRANSITION_MAP_HPP
#include<boost/bimap.hpp>
#include<boost/bimap/multiset_of.hpp>
#include<map>
#include<utility>
#include<string>
#include<iostream>

/**
 * This defines transition map class using boost bimap framework.
 * It is a map from integers to integers which can be used used 
 * in bot directions. 
 *
 */


using namespace boost::bimaps;
typedef boost::bimap<multiset_of<int>,multiset_of<int> > tmap;
typedef tmap::value_type position;
typedef tmap::left_const_iterator left_const_iterator;
typedef tmap::right_const_iterator right_const_iterator;
typedef std::pair<left_const_iterator,left_const_iterator> lpair;
typedef std::pair<right_const_iterator,right_const_iterator> rpair;

class transition_map{
private:
  std::map<int,tmap> chan_maps;
public:
  /** 
   * Constructor
   * 
   */
  transition_map(){};
  /** 
   * Copy constructor
   * 
   * @param tm 
   */
  transition_map(const transition_map& tm);
  /** 
   * Copy assingment
   * 
   * @param tm 
   * 
   * @return 
   */
  transition_map& operator=(const transition_map& tm);
  /** 
   * Set bimap (i.e. channel ) with key i to transition map
   * 
   * @param i 
   * @param tm 
   */
  void set_map(int i,tmap tm);
  /** 
   * Set bimap (i.e. channel) to the end with largest key
   * 
   * @param tm 
   */
  void set_map(tmap tm);
  /** 
   *  Return bimap (i.e. channel) 
   * 
   * 
   * @return bimap
   */
  tmap operator()(int k);
  /** 
   *  Return bimap (i.e. channel) 
   * 
   * 
   * @return bimap
   */
  tmap get_map(int k);
  


};

/** 
 * Template to print the contents of a generic bimap
 * 
 * @param map 
 * @param separator std::string 
 * @param os std::ostream object
 */
template< class MapType >
void print_map(const MapType & map,
               const std::string & separator,
               std::ostream & os )
{
    typedef typename MapType::const_iterator const_iterator;

    for( const_iterator i = map.begin(), iend = map.end(); i != iend; ++i )
    {
        os << i->first << separator << i->second << std::endl;
    }
};

#endif
